package com.example.myapplication;

import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.myapplication.adapter.ChatAdapter;
import com.example.myapplication.adapter.ChatInfo;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

public class ChatActivity extends BaseActivity {

    public ListView listView;
    public WebSocket mSocket = null;
    public List<ChatInfo> chatInfos = new ArrayList<>();
    public ChatAdapter chatAdapter = null;
    // 是否开始录音
    public Boolean isStart = false;
    // debug bar
    public TextView output = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);
        // debug栏
        output = findViewById(R.id.debugbar);
        output.setMovementMethod(new ScrollingMovementMethod());

        // 主动授权
        checkPermission();

        // 初始化拍照
        initPicture();

        // 链接websocket
        startWS();

        final Toast toast = initToast();
        output("初始化。。。");

        // 绑定adapter
        listView = findViewById(R.id.list_view);
        chatAdapter = new ChatAdapter(ChatActivity.this, chatInfos);
        listView.setAdapter(chatAdapter);
        // 自动滚动屏幕到最底端
        listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

        // listview元素点击事件监听
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                ChatInfo info = (ChatInfo) parent.getItemAtPosition(position);
                if (info.isRecord()) {
                    play(info.getPath());
                    toast.setText("语音消息" + info.getPath());
                } else if (info.isImage()) {
                    toast.setText("图片消息");
                } else {
                    toast.setText("文本消息");
                }
                toast.show();
            }
        });

        // 发送文本消息
        Button send = findViewById(R.id.send);
        final TextView text_msg = findViewById(R.id.text_msg);
        send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                submit(text_msg);
            }
        });

        // 回车提交
        text_msg.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == 6) {
                    submit(text_msg);
                    return true;
                }
                return false;
            }
        });

        final Button record = findViewById(R.id.record);
        record.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!isStart) {
                    startRecord();
                    record.setText("停止录制");
                    isStart = true;
                } else {
                    record.setText("开始录制");
                    isStart = false;
                    // 停止录音
                    stopRecord();
                    // 上传至七牛云
                    upload();
                }
            }
        });

        // 拍照
        Button photo = findViewById(R.id.photo);
        photo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getUploadToken();
                startPhoto();
            }
        });

        // 相冊选择
        Button choose = findViewById(R.id.choose_photo);
        choose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getUploadToken();
                openPhotos();
            }
        });
    }

    // 拍照或选中照片后续处理
    @Override
    protected void onPictureHandle(String path) {
        upload(path, null, UPLOAD_TYPE.IMAGE);
    }

    @Override
    protected void uploadSucessHandle(String key, UPLOAD_TYPE uploadType) {
        switch (uploadType) {
            case RECORD:
                submitRecord(key);
                toast.setText("ChatActivity.handle.RECORD:" + key);
                toast.show();
                break;
            case IMAGE:
                submitImage(key);
                toast.setText("ChatActivity.handle.IMAGE:" + key);
                toast.show();
                break;
        }
    }

    private void submit(TextView text_msg) {
        if (text_msg.getText().length() > 0) {
            String msg = text_msg.getText().toString();
            text_msg.setText("");
            submit("text", msg);
        }
    }

    public void submitRecord(String key) {
        submit("record", key);
    }

    public void submitImage(String key) {
        submit("image", key);
    }

    public void submit(String type, String data) {
        try {
            JSONObject send = new JSONObject();
            send.put("type", type);
            send.put("data", data);
            mSocket.send(send.toString());
        } catch (JSONException e) {
            outputToListView("JSONException：" + e.getMessage());
        }
    }

    private void startWS() {
        OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
                .readTimeout(3, TimeUnit.SECONDS)//设置读取超时时间
                .writeTimeout(3, TimeUnit.SECONDS)//设置写的超时时间
                .connectTimeout(3, TimeUnit.SECONDS)//设置连接超时时间
                .build();

        Request request = new Request.Builder().url("ws://118.24.26.76:9502").build();
        EchoWebSocketListener socketListener = new EchoWebSocketListener();
        mOkHttpClient.newWebSocket(request, socketListener);
        mOkHttpClient.dispatcher().executorService().shutdown();
    }


    // websocket 连接事件监听

    private final class EchoWebSocketListener extends WebSocketListener {

        @Override
        public void onOpen(WebSocket webSocket, Response response) {
            super.onOpen(webSocket, response);
            mSocket = webSocket;

            output("服务器连接成功！");

            // 获取七牛云token
            getQiniuToken();
            // 定时检测七牛token
            timerCheckToken();
        }

        @Override
        public void onMessage(WebSocket webSocket, ByteString bytes) {
            super.onMessage(webSocket, bytes);
            outputToListView("ByteString:receive bytes:" + bytes.hex());
        }

        @Override
        public void onMessage(WebSocket webSocket, String text) {
            super.onMessage(webSocket, text);
            try {
                JSONObject json = new JSONObject(text);
                int is_self = json.has("is_self") ? json.getInt("is_self") : 0;
                String data = json.has("data") ? json.getString("data") : "";
                String path = json.has("path") ? json.get("path").toString() : "";
                // 消息分类
                String type = json.has("type") ? json.get("type").toString() : null;
                assert type != null;

                switch (type) {
                    case "ping":
                        JSONObject response = new JSONObject();
                        response.put("type", "pong");
                        mSocket.send(response.toString());
                        return;

                    case "text":
                        if (is_self == 1) {
                            outputToListViewSelfText(data);
                        } else {
                            outputToListView(data);
                        }
                        break;

                    case "record":
                        if (is_self == 1) {
                            outputToListViewSelfRecord(data, path);
                        } else {
                            outputTolistViewRecord(data, path);
                        }
                        break;

                    case "image":
                        if (is_self == 1) {
                            outputToListViewSelfImage(data, path);
                        } else {
                            outputTolistViewImage(data, path);
                        }
                        break;

                    case "token":
                        uploadToken = json.get("data").toString();
                        Date date = new Date();
                        output("upload token 已获取~ 时间：" + String.format("%ty-%tm-%td %tH:%tM:%tS", date, date, date, date, date, date));
                        // 3600秒后过期，3000秒置null
                        Timer nTimer = new Timer();
                        nTimer.schedule(new TimerTask() {
                            @Override
                            public void run() {
                                uploadToken = null;
                            }
                        }, 60000 * 5);
                        break;
                }

                // 调试websocket消息
                output("onMessage: " + text);

            } catch (JSONException e) {
                outputToListView("json decode faild:" + e.getMessage());
            }

        }

        @Override
        public void onClosed(WebSocket webSocket, int code, String reason) {
            super.onClosed(webSocket, code, reason);
            outputToListView("closed:" + reason);
            mSocket = null;
        }

        @Override
        public void onClosing(WebSocket webSocket, int code, String reason) {
            super.onClosing(webSocket, code, reason);
            outputToListView("closing:" + reason);
            mSocket = null;
        }

        @Override
        public void onFailure(WebSocket webSocket, Throwable t, Response response) {
            super.onFailure(webSocket, t, response);
            outputToListView("failure:" + t.getMessage());
            mSocket = null;
        }
    }

    private void timerCheckToken() {
        // 每两秒检测一次，如果token为null就重新请求
        Timer nTimer = new Timer();
        nTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (uploadToken == null) {
                    getQiniuToken();
                }
            }
        }, 500, 1000);
    }

    private void getQiniuToken() {
        try {
            JSONObject send = new JSONObject();
            send.put("type", "uploadToken");
            mSocket.send(send.toString());
        } catch (JSONException e) {
            outputToListView("uploadToken json:" + e.getMessage());
        }
    }

    private void output(final String text) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                output.setText(output.getText().toString() + "\n" + text);
                output.scrollTo(0, (output.getLineCount() * output.getLineHeight()) - output.getHeight());
            }
        });
    }

    private void outputToListView(final String text) {
        outputToListView(text, ChatInfo.text, "");
    }

    private void outputTolistViewRecord(String text, String path) {
        outputToListView(text, ChatInfo.record, path);
    }

    private void outputTolistViewImage(String text, String path) {
        HashMap param = new HashMap();
        param.put("text", text);
        param.put("type", "other");
        downloadImg(path, param);
    }

    @Override
    public void downloadImageHandler(String path, HashMap param) {
        Log.d(TAG, "downloadImageHandler: ");
        String text = param.get("text").toString();
        String belong = param.get("type").toString();
        if (belong == null || text == null) {
            Log.d(TAG, "downloadImageHandler: belong/text is null");
            return;
        }
        switch (belong) {
            case "self":
                outputToListViewSelf(text, ChatInfo.image, path);
                break;
            case "other":
                outputToListView(text, ChatInfo.image, path);
                break;
        }
    }

    private void outputToListView(final String text, final int dataType, final String path) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                chatInfos.add(new ChatInfo(text, ChatInfo.other, dataType, path));
                chatAdapter.notifyDataSetChanged();
            }
        });
    }

    private void outputToListViewSelfText(final String text) {
        outputToListViewSelf(text, ChatInfo.text, "");
    }

    private void outputToListViewSelfRecord(final String text, final String path) {
        outputToListViewSelf(text, ChatInfo.record, path);
    }

    private void outputToListViewSelfImage(String text, String path) {
        HashMap param = new HashMap();
        param.put("text", text);
        param.put("type", "self");
        downloadImg(path, param);
    }

    private void outputToListViewSelf(final String text, final int dataType, final String path) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                chatInfos.add(new ChatInfo(text, ChatInfo.self, dataType, path));
                chatAdapter.notifyDataSetChanged();
            }
        });
    }

}
